#pragma once
#include <iostream>
#include <string>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <fstream>
#include <mutex>

namespace ns_LOG
{
    const char *filename = "./log.txt";
    bool issave = false;
    
    enum
    {
        INFO = 0,
        DEBUG,
        WARNNING,
        ERROR,
        FATAL
    };

    std::string GetLevel(int level)
    {
        std::string ret;
        switch(level)
        {
            case 0:
                ret = "INFO";
                break;
            case 1:
                ret = "DEBUG";
                break;
            case 2:
                ret = "WARNNING";
                break;
            case 3:
                ret = "ERROR";
                break;
            case 4:
                ret = "FATAL";
                break;
            default:
                ret = "未知";
                break;
        }
        return ret;
    }
    std::string Gettime()
    {

        char ch[1024];
        time_t t = time(nullptr);

        struct tm *tm = localtime(&t);

        snprintf(ch, sizeof(ch), "%d-%02d-%02d,%02d:%02d:%02d",
                 tm->tm_year + 1900,
                 tm->tm_mon + 1,
                 tm->tm_mday,
                 tm->tm_hour,
                 tm->tm_min,
                 tm->tm_sec);

        return ch;
    }

    void GetLog(std::string filename, int line, bool issave,int level,const char *format, ...)
    {
        std::string slevel = GetLevel(level);
        std::string time = Gettime();
        std::string sline = std::to_string(line);
        std::string pid = std::to_string(getpid());

        // 处理可变参数部分
        va_list va;
        va_start(va, format);
        char buffer[1024];

        vsnprintf(buffer, sizeof(buffer), format, va);
        va_end(va);
        std::string msg = "[" + time + "]" + "[" + slevel + "]" + "[" + pid + "]" + "[" + filename + "]" + "[" + sline + "]" + ": " + buffer + "\n";

        std::mutex m;
        m.lock();
        if (issave == false)
        {
            std::cout << msg;
        }
        else
        {
            std::ofstream f(filename);
            if (!f.is_open())
            {
                std::cout << "file to open log.txt" << std::endl;
                return;
            }
            f << msg.c_str();
            f.close();
        }
        m.unlock();
    }

#define LOG(level,format, ...)                                        \
    do                                                          \
    {                                                           \
        GetLog(__FILE__, __LINE__,issave, level, format, ##__VA_ARGS__); \
    } while (0);

#define Eablecout()     \
    do                  \
    {                   \
        issave = false; \
    } while (0);

#define Eablefile()    \
    do                 \
    {                  \
        issave = true; \
    } while (0);

}